#ifndef GAMEENGINE_GEOMETRY_TRGL2D_H
#define GAMEENGINE_GEOMETRY_TRGL2D_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Location/point2d.h>
#include <GameEngine/Geometry/Location/vector2d.h>
#include <GameEngine/Geometry/Lines/line2d.h>
#include <GameEngine/Geometry/Core/coords2d.h>
#include <GameEngine/Geometry/CoordinateSystems/transformer2d.h>

#include <GameEngine/Geometry/Surfaces/trgl2d_defs.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


//! Class used to represent 2D triangles
/*!
 *  This class is quite similar to the Trgl2dFast class and shares most of its interface. The
 *  most notable difference, however, is the strategy for memory management: while the
 *  the Trgl2dFast class only uses references to the points, the Trgl2d class stores the
 *  geometry of the three associated points. This releases most of the constraints associated
 *  to the Trgl2dFast class, but makes Trgl2d items much slower to build.
 *
 *  Generally, it is recommanded to use this class rather than the Trgl2dFast class when client
 *  code requires more than on-the-fly geometric queries, e.g., when the triangle is persistant
 *  and should be kept in memory for some time.
 *
 @note A 2D triangle is made of three 2D points
 @note Most algorithms expect floating point operations. Type T should therefore
       not be an integer type
 */
template <class T>
class Trgl2d {

public:
	Trgl2d();
	Trgl2d(const Point2d<T>& p1, const Point2d<T>& p2, const Point2d<T>& p3);
	Trgl2d(const Trgl2d& rhs);
	virtual ~Trgl2d();
	Trgl2d& operator=(const Trgl2d& rhs);

	Point2d<T>& p1();
	const Point2d<T>& p1() const;
	Point2d<T>& p2();
	const Point2d<T>& p2() const;
	Point2d<T>& p3();
	const Point2d<T>& p3() const;

	Vector2d<T> u_axis() const;
	Vector2d<T> v_axis() const;

	Point2d<T> point(const Coords2d<T>& coords) const;
	Coords2d<T> coordinates(const Point2d<T>& pt) const;
	Transformer2d<T> transformer() const;

	Point2d<T>& operator[](Trgl2D::Index index);
	const Point2d<T>& operator[](Trgl2D::Index index) const;

	bool inside(const Point2d<T>& rhs, bool strict = false) const;
	bool intersection(const Line2d<T>& rhs, T& line_coordinate1, T& line_coordinate2, IntersectionType::Type* type = nil) const;
	bool closest_point(const Point2d<T>& rhs, Coords2d<T>& coords) const;
	Point2d<T> closest_point(const Point2d<T>& rhs) const;

	T perimeter() const;
	T area() const;

	bool degenerate(const T& tolerance = 0.000001) const;
	static bool in_trgl(const Coords2d<T>& coords, bool strict=false);

protected:
	//! Point coordinates
	Point2d<T> points_[3];
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Surfaces/trgl2d.hpp>

#endif
